<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
	<meta name="keywords" content="fescar、seata、分布式事务" />
	<meta name="description" content="seata-sourcecode-client-bootstrap" />
	<!-- 网页标签标题 -->
	<title>分布式事务Seata源码-Client端启动流程</title>
  <link rel="shortcut icon" href="/img/seata_logo_small.jpeg"/>
	<link rel="stylesheet" href="/build/blogDetail.css" />
</head>
<body>
	<div id="root"><div class="blog-detail-page" data-reactroot=""><header class="header-container header-container-normal"><div class="header-body"><a href="/zh-cn/index.html"><img class="logo" src="//img.alicdn.com/tfs/TB1gqL1w4D1gK0jSZFyXXciOVXa-1497-401.png"/></a><div class="search search-normal"><span class="icon-search"></span></div><span class="language-switch language-switch-normal">En</span><div class="header-menu"><img class="header-menu-toggle" src="https://img.alicdn.com/tfs/TB14eEmw7P2gK0jSZPxXXacQpXa-38-32.png"/><ul><li class="menu-item menu-item-normal"><a href="/zh-cn/index.html" target="_self">首页</a></li><li class="menu-item menu-item-normal"><a href="/zh-cn/docs/overview/what-is-seata.html" target="_self">文档</a></li><li class="menu-item menu-item-normal"><a href="/zh-cn/docs/developers/developers_dev.html" target="_self">开发者</a></li><li class="menu-item menu-item-normal menu-item-normal-active"><a href="/zh-cn/blog/index.html" target="_self">博客</a></li><li class="menu-item menu-item-normal"><a href="/zh-cn/community/index.html" target="_self">社区</a></li><li class="menu-item menu-item-normal"><a href="/zh-cn/blog/download.html" target="_self">下载</a></li></ul></div></div></header><section class="blog-content markdown-body"><h2>【分布式事务Seata源码解读二】Client端启动流程</h2>
<p>本文从源码的角度分析一下AT模式下Client端启动流程，所谓的Client端，即业务应用方。分布式事务分为三个模块：TC、TM、RM。其中TC位于seata-server端，而TM、RM通过SDK的方式运行在client端。</p>
<p>下图展示了Seata官方Demo的一个分布式事务场景，分为如下几个微服务，共同实现了一个下订单、扣库存、扣余额的分布式事务。</p>
<ul>
<li><strong>BusinessService：</strong> 业务服务，下单服务的入口</li>
<li><strong>StorageService：</strong> 库存微服务，用于扣减商品库存</li>
<li><strong>OrderService：</strong> 订单微服务，创建订单</li>
<li><strong>AccountService：</strong> 账户微服务，扣减用户账户的余额</li>
</ul>
<p><img src="https://img-blog.csdnimg.cn/20200820184156758.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTE0NTg0OA==,size_16,color_FFFFFF,t_70#pic_center" alt="在这里插入图片描述"></p>
<p>从上图也可以看出，在AT模式下Seata Client端主要通过如下三个模块来实现分布式事务：</p>
<ul>
<li><strong>GlobalTransactionScanner：</strong>  GlobalTransactionScanner负责初始TM、RM模块，并为添加分布式事务注解的方法添加拦截器，拦截器负责全局事务的开启、提交或回滚</li>
<li><strong>DatasourceProxy：</strong> DatasourceProxy为DataSource添加拦截，拦截器会拦截所有SQL执行，并作为RM事务参与方的角色参与分布式事务执行。</li>
<li><strong>Rpc Interceptor：</strong> 在上一篇<a href="https://blog.csdn.net/weixin_45145848/article/details/106930538">分布式事务Seata源码解读一</a>中有提到分布式事务的几个核心要点，其中有一个是分布式事务的跨服务实例传播。Rpc Interceptor的职责就是负责在多个微服务之间传播事务。</li>
</ul>
<h2>seata-spring-boot-starter</h2>
<p>引用seata分布式事务SDK有两种方式，依赖seata-all或者seata-spring-boot-starter，推荐使用seata-spring-boot-starter，因为该starter已经自动注入了上面提到的三个模块，用户只要添加相应的配置，在业务代码添加全局分布式事务注解即可。下面从seata-spring-boot-starter项目中的代码入手：</p>
<p>如下图所示是seata-spring-boot-starter的项目结构：
<img src="https://img-blog.csdnimg.cn/20200810204518853.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTE0NTg0OA==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述">
主要分为以下几个模块：</p>
<ul>
<li><strong>properties：</strong> properties目录下都是Springboot 适配seata的相关配置类，即可以通过SpringBoot的配置方式来Seata的相关参数</li>
<li><strong>provider：</strong> provider目录下的类负责把Springboot、SpringCloud的配置适配到Seata配置中</li>
<li><strong>resources：</strong> resources目录下主要有两个文件，spring.factories用于注册Springboot的自动装配类，ExtConfigurationProvider用于注册SpringbootConfigurationProvider类，该Provider类负责把SpringBoot的相关配置类适配到Seata中。</li>
</ul>
<p>对于springboot-starter项目，我们先查看resources/META-INF/spring.factories文件：</p>
<pre><code class="language-properties"><span class="hljs-comment"># Auto Configure</span>
<span class="hljs-meta">org.springframework.boot.autoconfigure.EnableAutoConfiguration</span>=<span class="hljs-string"></span>
<span class="hljs-attr">io.seata.spring.boot.autoconfigure.SeataAutoConfiguration</span>
</code></pre>
<p>可以看到在spring.factories中配置了自动装配类：SeataAutoConfiguration，在该装配类中主要注入了GlobalTransactionScanner和seataAutoDataSourceProxyCreator两个实例。代码如下：</p>
<pre><code class="language-java"><span class="hljs-meta">@ComponentScan</span>(basePackages = <span class="hljs-string">"io.seata.spring.boot.autoconfigure.properties"</span>)
<span class="hljs-meta">@ConditionalOnProperty</span>(prefix = StarterConstants.SEATA_PREFIX, name = <span class="hljs-string">"enabled"</span>,
        havingValue = <span class="hljs-string">"true"</span>,
        matchIfMissing = <span class="hljs-keyword">true</span>)
<span class="hljs-meta">@Configuration</span>
<span class="hljs-meta">@EnableConfigurationProperties</span>({SeataProperties.class})
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SeataAutoConfiguration</span> </span>{

  ...
  
  <span class="hljs-comment">// GlobalTransactionScanner负责为添加GlobalTransaction注解的方法添加拦截器，</span>
  <span class="hljs-comment">// 并且负责初始化RM、TM</span>
  <span class="hljs-meta">@Bean</span>
  <span class="hljs-meta">@DependsOn</span>({BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER, BEAN_NAME_FAILURE_HANDLER})
  <span class="hljs-meta">@ConditionalOnMissingBean</span>(GlobalTransactionScanner.class)
  <span class="hljs-function"><span class="hljs-keyword">public</span> GlobalTransactionScanner <span class="hljs-title">globalTransactionScanner</span><span class="hljs-params">(SeataProperties seataProperties,
                                                           FailureHandler failureHandler)</span> </span>{
    <span class="hljs-keyword">if</span> (LOGGER.isInfoEnabled()) {
      LOGGER.info(<span class="hljs-string">"Automatically configure Seata"</span>);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> GlobalTransactionScanner(seataProperties.getApplicationId(),
            seataProperties.getTxServiceGroup(),
            failureHandler);
  }
  
  <span class="hljs-comment">// SeataAutoDataSourceProxyCreator负责为Spring中的所有DataSource生成代理对象，</span>
  <span class="hljs-comment">// 从而实现拦截所有SQL的执行</span>
  <span class="hljs-meta">@Bean</span>(BEAN_NAME_SEATA_AUTO_DATA_SOURCE_PROXY_CREATOR)
  <span class="hljs-meta">@ConditionalOnProperty</span>(prefix = StarterConstants.SEATA_PREFIX, name = {
          <span class="hljs-string">"enableAutoDataSourceProxy"</span>, <span class="hljs-string">"enable-auto"</span> +
          <span class="hljs-string">"-data-source-proxy"</span>}, havingValue = <span class="hljs-string">"true"</span>, matchIfMissing = <span class="hljs-keyword">true</span>)
  <span class="hljs-meta">@ConditionalOnMissingBean</span>(SeataAutoDataSourceProxyCreator.class)
  <span class="hljs-function"><span class="hljs-keyword">public</span> SeataAutoDataSourceProxyCreator <span class="hljs-title">seataAutoDataSourceProxyCreator</span><span class="hljs-params">(SeataProperties seataProperties)</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> SeataAutoDataSourceProxyCreator(seataProperties.isUseJdkProxy(),
            seataProperties.getExcludesForAutoProxying());
  }
}
</code></pre>
<h3>GlobalTransactionScanner</h3>
<p>GlobalTransactionScanner继承于AutoProxyCreator，AutoProxyCreator是Spring中实现AOP的一种方式，可以拦截Spring中的所有实例，判断是否需要进行代理。下面列出了GlobalTransactionScanner中一些比较重要的字段和拦截代理的核心方法：</p>
<pre><code class="language-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GlobalTransactionScanner</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractAutoProxyCreator</span>
        <span class="hljs-keyword">implements</span> <span class="hljs-title">InitializingBean</span>, <span class="hljs-title">ApplicationContextAware</span>,
        <span class="hljs-title">DisposableBean</span> </span>{
  ...
  <span class="hljs-comment">// interceptor字段是对应一个代理对象的拦截器，</span>
  <span class="hljs-comment">// 可以认为是一个临时变量，有效期是一个被代理对象</span>
  <span class="hljs-keyword">private</span> MethodInterceptor interceptor;
  
  <span class="hljs-comment">// globalTransactionalInterceptor是通用的Interceptor，</span>
  <span class="hljs-comment">// 非TCC事务方式的都使用该Interceptor</span>
  <span class="hljs-keyword">private</span> MethodInterceptor globalTransactionalInterceptor;
  
  <span class="hljs-comment">// PROXYED_SET存储已经代理过的实例，防止重复处理</span>
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Set&lt;String&gt; PROXYED_SET = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();
  
  <span class="hljs-comment">// applicationId是一个服务的唯一标识，</span>
  <span class="hljs-comment">// 对应springcloud项目中的spring.application.name</span>
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String applicationId;
  <span class="hljs-comment">// 事务的分组标识，参考文章wiki：http://seata.io/zh-cn/docs/user/txgroup/transaction-group.html</span>
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String txServiceGroup;
  
  ...

  <span class="hljs-comment">// 判断是否需要代理目标对象，如果需要代理，则生成拦截器赋值到类变量interceptor中</span>
  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">protected</span> Object <span class="hljs-title">wrapIfNecessary</span><span class="hljs-params">(Object bean, String beanName, Object cacheKey)</span> </span>{
  	<span class="hljs-comment">// 判断是否禁用分布式事务</span>
    <span class="hljs-keyword">if</span> (disableGlobalTransaction) {
      <span class="hljs-keyword">return</span> bean;
    }
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">synchronized</span> (PROXYED_SET) {
        <span class="hljs-keyword">if</span> (PROXYED_SET.contains(beanName)) {
          <span class="hljs-keyword">return</span> bean;
        }
        
        <span class="hljs-comment">// 每次处理一个被代理对象时先把interceptor置为null，所以interceptor的</span>
        <span class="hljs-comment">// 生命周期是一个被代理对象，由于是在另外一个方法getAdvicesAndAdvisorsForBean</span>
        <span class="hljs-comment">// 中使用interceptor，所以该interceptor要定义为一个类变量</span>
        interceptor = <span class="hljs-keyword">null</span>;
        
        <span class="hljs-comment">// 判断是否是TCC事务模式，判断的主要依据是方法上是否有TwoPhaseBusinessAction注解</span>
        <span class="hljs-keyword">if</span> (TCCBeanParserUtils.isTccAutoProxy(bean, beanName,
                applicationContext)) {
          <span class="hljs-comment">// 创建一个TCC事务的拦截器</span>
          interceptor =
                  <span class="hljs-keyword">new</span> TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName));
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-comment">// 获取待处理对象的class类型</span>
          Class&lt;?&gt; serviceInterface = SpringProxyUtils.findTargetClass(bean);
          <span class="hljs-comment">// 获取待处理对象继承的所有接口</span>
          Class&lt;?&gt;[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean);
          
          <span class="hljs-comment">// 如果待处理对象的class或者继承的接口上有GlobalTransactional注解，</span>
          <span class="hljs-comment">// 或者待处理对象的class的任一个方法上有GlobalTransactional或者</span>
          <span class="hljs-comment">// GlobalLock注解则返回true，即需要被代理</span>
          <span class="hljs-keyword">if</span> (!existsAnnotation(<span class="hljs-keyword">new</span> Class[]{serviceInterface})
                  &amp;&amp; !existsAnnotation(interfacesIfJdk)) {
            <span class="hljs-keyword">return</span> bean;
          }
          
          <span class="hljs-comment">// 如果interceptor为null，即不是TCC模式，</span>
          <span class="hljs-comment">// 则使用globalTransactionalInterceptor作为拦截器</span>
          <span class="hljs-keyword">if</span> (interceptor == <span class="hljs-keyword">null</span>) {
            <span class="hljs-comment">// globalTransactionalInterceptor只会被创建一次</span>
            <span class="hljs-keyword">if</span> (globalTransactionalInterceptor == <span class="hljs-keyword">null</span>) {
              globalTransactionalInterceptor =
                      <span class="hljs-keyword">new</span> GlobalTransactionalInterceptor(failureHandlerHook);
              ConfigurationCache.addConfigListener(
                      ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,
                      (ConfigurationChangeListener) globalTransactionalInterceptor);
            }
            interceptor = globalTransactionalInterceptor;
          }
        }

        <span class="hljs-keyword">if</span> (!AopUtils.isAopProxy(bean)) {
          <span class="hljs-comment">// 如果bean本身不是Proxy对象，则直接调用父类的wrapIfNecessary生成代理对象即可</span>
          <span class="hljs-comment">// 在父类中会调用getAdvicesAndAdvisorsForBean获取到上面定义的interceptor</span>
          bean = <span class="hljs-keyword">super</span>.wrapIfNecessary(bean, beanName, cacheKey);
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-comment">// 如果该bean已经是代理对象了，则直接在代理对象的拦截调用链AdvisedSupport</span>
          <span class="hljs-comment">// 上直接添加新的interceptor即可。</span>
          AdvisedSupport advised = SpringProxyUtils.getAdvisedSupport(bean);
          Advisor[] advisor = buildAdvisors(beanName,
                  getAdvicesAndAdvisorsForBean(<span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>));
          <span class="hljs-keyword">for</span> (Advisor avr : advisor) {
            advised.addAdvisor(<span class="hljs-number">0</span>, avr);
          }
        }         
        <span class="hljs-comment">// 标识该beanName已经处理过了</span>
        PROXYED_SET.add(beanName);
        <span class="hljs-keyword">return</span> bean;
      }
    } <span class="hljs-keyword">catch</span> (Exception exx) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(exx);
    }
  }
  
  <span class="hljs-comment">// 返回wrapIfNecessary方法中计算出的interceptor对象</span>
  <span class="hljs-meta">@Override</span>
  <span class="hljs-keyword">protected</span> Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName,
                                                  TargetSource customTargetSource)
          <span class="hljs-keyword">throws</span> BeansException {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Object[]{interceptor};
  }
}
</code></pre>
<p>上面介绍了GlobalTransactionScanner是如何通过注解拦截全局事务的，具体拦截器实现为TccActionInterceptor和GlobalTransactionalInterceptor，对于AT模式来说我们主要关心GlobalTransactionalInterceptor，在后续的文章中会介绍GlobalTransactionalInterceptor的具体实现。</p>
<p>另外GloabalTransactionScanner还负责TM、RM的初始化工作，是在initClient方法中实现的：</p>
<pre><code class="language-java"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initClient</span><span class="hljs-params">()</span> </span>{
    ...
    
    <span class="hljs-comment">//初始化TM</span>
    TMClient.init(applicationId, txServiceGroup);
    ...
    
    <span class="hljs-comment">//初始化RM</span>
    RMClient.init(applicationId, txServiceGroup);
	...
	
    <span class="hljs-comment">// 注册Spring shutdown的回调，用来释放资源</span>
    registerSpringShutdownHook();

 }
</code></pre>
<p>TMClient、RMClient都是Seata基于Netty实现的Rpc框架的客户端类，只是业务逻辑不同，由于TMClient相对来说更简单一些，我们以RMClient为例看一下源码：</p>
<pre><code class="language-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RMClient</span> </span>{
  <span class="hljs-comment">// RMClient的init是一个static方法，创建了一个RmNettyRemotingClient实例，并调用init方法</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span><span class="hljs-params">(String applicationId, String transactionServiceGroup)</span> </span>{
    RmNettyRemotingClient rmNettyRemotingClient =
            RmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup);
    rmNettyRemotingClient.setResourceManager(DefaultResourceManager.get());
    rmNettyRemotingClient.setTransactionMessageHandler(DefaultRMHandler.get());
    rmNettyRemotingClient.init();
  }
}
</code></pre>
<p>RmNettyRemotingClient的实现如下：</p>
<pre><code class="language-java"><span class="hljs-meta">@Sharable</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RmNettyRemotingClient</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AbstractNettyRemotingClient</span> </span>{
  <span class="hljs-comment">// ResourceManager负责处理事务参与方，支持AT、TCC、Saga三种模式</span>
  <span class="hljs-keyword">private</span> ResourceManager resourceManager;
  <span class="hljs-comment">// RmNettyRemotingClient单例</span>
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">volatile</span> RmNettyRemotingClient instance;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AtomicBoolean initialized = <span class="hljs-keyword">new</span> AtomicBoolean(<span class="hljs-keyword">false</span>);
  <span class="hljs-comment">// 微服务的唯一标识</span>
  <span class="hljs-keyword">private</span> String applicationId;
  <span class="hljs-comment">// 分布式事务分组名称</span>
  <span class="hljs-keyword">private</span> String transactionServiceGroup;
  
  <span class="hljs-comment">// RMClient中init方法会调用该init方法</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-comment">// 注册Seata自定义Rpc的Processor</span>
    registerProcessor();
    <span class="hljs-keyword">if</span> (initialized.compareAndSet(<span class="hljs-keyword">false</span>, <span class="hljs-keyword">true</span>)) {
      <span class="hljs-comment">// 调用父类的init方法，在父类中负责Netty的初始化，与Seata-Server建立连接</span>
      <span class="hljs-keyword">super</span>.init();
    }
  }
  
  <span class="hljs-comment">// 注册Seata自定义Rpc的Processor</span>
  <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">registerProcessor</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-comment">// 1.注册Seata-Server发起branchCommit的处理Processor</span>
    RmBranchCommitProcessor rmBranchCommitProcessor =
            <span class="hljs-keyword">new</span> RmBranchCommitProcessor(getTransactionMessageHandler(), <span class="hljs-keyword">this</span>);
    <span class="hljs-keyword">super</span>.registerProcessor(MessageType.TYPE_BRANCH_COMMIT, rmBranchCommitProcessor,
            messageExecutor);
            
    <span class="hljs-comment">// 2.注册Seata-Server发起branchRollback的处理Processor</span>
    RmBranchRollbackProcessor rmBranchRollbackProcessor =
            <span class="hljs-keyword">new</span> RmBranchRollbackProcessor(getTransactionMessageHandler(), <span class="hljs-keyword">this</span>);
    <span class="hljs-keyword">super</span>.registerProcessor(MessageType.TYPE_BRANCH_ROLLBACK, rmBranchRollbackProcessor
            , messageExecutor);
            
    <span class="hljs-comment">// 3.注册Seata-Server发起删除undoLog的处理Processor</span>
    RmUndoLogProcessor rmUndoLogProcessor =
            <span class="hljs-keyword">new</span> RmUndoLogProcessor(getTransactionMessageHandler());
    <span class="hljs-keyword">super</span>.registerProcessor(MessageType.TYPE_RM_DELETE_UNDOLOG, rmUndoLogProcessor,
            messageExecutor);
            
    <span class="hljs-comment">// 4.注册Seata-Server返回Response的处理Processor，ClientOnResponseProcessor</span>
    <span class="hljs-comment">// 用于处理由Client主动发起Request，Seata-Server返回的Response。</span>
    <span class="hljs-comment">// ClientOnResponseProcessor负责把Client发送的Request和Seata-Server</span>
    <span class="hljs-comment">// 返回的Response对应起来，从而实现Rpc</span>
    ClientOnResponseProcessor onResponseProcessor =
            <span class="hljs-keyword">new</span> ClientOnResponseProcessor(mergeMsgMap, <span class="hljs-keyword">super</span>.getFutures(),
                    getTransactionMessageHandler());
    <span class="hljs-keyword">super</span>.registerProcessor(MessageType.TYPE_SEATA_MERGE_RESULT, onResponseProcessor,
            <span class="hljs-keyword">null</span>);
    <span class="hljs-keyword">super</span>.registerProcessor(MessageType.TYPE_BRANCH_REGISTER_RESULT,
            onResponseProcessor, <span class="hljs-keyword">null</span>);
    <span class="hljs-keyword">super</span>.registerProcessor(MessageType.TYPE_BRANCH_STATUS_REPORT_RESULT,
            onResponseProcessor, <span class="hljs-keyword">null</span>);
    <span class="hljs-keyword">super</span>.registerProcessor(MessageType.TYPE_GLOBAL_LOCK_QUERY_RESULT,
            onResponseProcessor, <span class="hljs-keyword">null</span>);
    <span class="hljs-keyword">super</span>.registerProcessor(MessageType.TYPE_REG_RM_RESULT, onResponseProcessor, <span class="hljs-keyword">null</span>);
    
    <span class="hljs-comment">// 5. 处理Seata-Server返回的Pong消息</span>
    ClientHeartbeatProcessor clientHeartbeatProcessor = <span class="hljs-keyword">new</span> ClientHeartbeatProcessor();
    <span class="hljs-keyword">super</span>.registerProcessor(MessageType.TYPE_HEARTBEAT_MSG, clientHeartbeatProcessor,
            <span class="hljs-keyword">null</span>);
  }
}
</code></pre>
<p>上面的逻辑看起来比较复杂，相关类也比较多，如：各种Processor、各种MessageType、TransactionMessageHandler、ResourceManager。其实本质上就是Rpc调用，分为Rm主动调用和Seata主动调用。</p>
<ul>
<li><strong>Rm主动调用方法：</strong> 如：注册分支、汇报分支状态、申请全局锁等。Rm主动调用的方法都需要在ClientOnResponseProcessor中处理Seata-Server返回的Response</li>
<li><strong>Seata-Server主动调用方法：</strong> 如：提交分支事务、回滚分支事务、删除undolog日志。Seata-Server主动调用的方法，Client端分别对应不同的Processor来处理，并且处理结束后要返回给Seata-Server处理结果Response。而事务提交、回滚的核心实现逻辑都在TransactionMessageHandler、ResourceManager中。</li>
</ul>
<p>关于TransactionMessageHandler、ResourceManager的具体实现也会在后续的章节中详细描述。</p>
<p>下一篇会介绍一下SeataAutoDataSourceProxyCreator、Rpc Interceptor是如何初始化以及拦截的。</p>
</section><footer class="footer-container"><div class="footer-body"><img src="//img.alicdn.com/tfs/TB1dGrSwVT7gK0jSZFpXXaTkpXa-4802-1285.png"/><p class="docsite-power">website powered by docsite</p><div class="cols-container"><div class="col col-12"><h3>愿景</h3><p>Seata 是一款阿里巴巴开源的分布式事务解决方案，致力于在微服务架构下提供高性能和简单易用的分布式事务服务。</p></div><div class="col col-6"><dl><dt>文档</dt><dd><a href="/zh-cn/docs/overview/what-is-seata.html" target="_self">Seata 是什么？</a></dd><dd><a href="/zh-cn/docs/user/quickstart.html" target="_self">快速开始</a></dd><dd><a href="https://github.com/seata/seata.github.io/issues/new" target="_self">报告文档问题</a></dd><dd><a href="https://github.com/seata/seata.github.io" target="_self">在Github上编辑此文档</a></dd></dl></div><div class="col col-6"><dl><dt>资源</dt><dd><a href="/zh-cn/blog/index.html" target="_self">博客</a></dd><dd><a href="/zh-cn/community/index.html" target="_self">社区</a></dd></dl></div></div><div class="copyright"><span>Copyright © 2019 Seata</span></div></div></footer></div></div>
	<script src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script>
	<script src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script>
	<script>
		window.rootPath = '';
  </script>
	<script src="/build/blogDetail.js"></script>
	<script>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?104e73ef0c18b416b27abb23757ed8ee";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
    </script>
</body>
</html>
